package myTest;

import com.sun.javafx.scene.control.skin.TextAreaSkin;

import java.util.ArrayList;
import java.util.PriorityQueue;
import java.util.Random;
import java.util.concurrent.*;

/**
 * Created by 杨志远 on 2017/5/29
 * email faryangsh@163.com.
 */
public class TestQueue {
    public static void main(String[] args) {
//        testConcurrentQueue();
//        testArrayBlockingQueue();
//        testLinkedBlockingQueue();
//        testArrayBlockingQueue2();
        testSynchronousQueue();
//        testPriorityQueue();
    }

    private static void testPriorityQueue() {
        PriorityQueue<Task> queue = new PriorityQueue<>();
        for (int i = 1; i < 10; i++) {
            int tmp = i;
            if (i % 2 == 0) {
                tmp = i * (-1);
            }
            Task task = new Task();
            task.setId(tmp);
            queue.add(task);
        }
        System.out.println(queue.toString());
        for (int i = 1; i < 10; i++) {
            queue.poll();
            System.out.println(queue.toString());
        }

    }

    static class Task implements Comparable<Task> {
        private int id;

        public void setId(int id) {
            this.id = id;
        }

        public int getId() {
            return id;
        }

        @Override
        public String toString() {
            return "Task{" +
                    "id=" + id +
                    '}';
        }

        @Override
        public int compareTo(Task task) {
            return this.id > task.id ? 1 : (this.id == task.id ? 0 : -1);
        }
    }

    private static void testSynchronousQueue() {
        SynchronousQueue<Integer> queue = new SynchronousQueue<>();
        Thread thread1 = new Thread(() -> {
            try {
                for (;;){
                    Thread.currentThread().sleep(500);
                    Integer take = queue.take();
                    System.out.printf("consume num: %s %n",take);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        Thread thread2 = new Thread(() -> {

           for (;;){
               try {
                   Thread.currentThread().sleep(500);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
               Random random = new Random(3);
               int i = random.nextInt(3);
               queue.add(i);
               System.out.printf("product num: %s %n",i);
           }
        });
        thread2.start();
        thread1.start();
       /* for (int i = 1; i < 5; i++) {
            boolean offer = queue.offer(i);
            System.out.print(queue.poll());
        }
        System.out.println(queue.toString());*/
    }

    private static void testArrayBlockingQueue2() {
        ArrayBlockingQueue queue = new ArrayBlockingQueue<String>(5);
        queue.add("1");
        queue.add("2");
        queue.add("3");
        queue.add("4");
        queue.add("5");
        ArrayList<String> list = new ArrayList<>();
        //批量从queue取出前三个元素放入集合中
        queue.drainTo(list, 3);
        System.out.println(list);
    }

    private static void testLinkedBlockingQueue() {
        //加上容量后就是有界队列，不加就是无界队列
        LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>(2);
//        LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>(2);
        queue.add("1");
        queue.add("1");
        queue.add("1");
        queue.add("1");
        System.out.println(queue.toString());
    }

    private static void testArrayBlockingQueue() {
        ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<String>(4);
        queue.add("1");
        queue.add("2");
        queue.add("3");
        queue.add("4");
        System.out.println(queue.toString());
        //这里使用了一个新的线程单独做队列的offer操作，添加了4个元素，已经加满了，但是底下有个poll操作，可以空出一个位置提供给下面offer一个5。
        //因此这里采用异步操作，使得offer等待过程中，queue会释放一个元素
        Thread thread = new Thread(() -> {
            try {
                //queue.offer("5", 3, TimeUnit.SECONDS)，表示可以容忍5秒钟的等待，如果5秒后，还不能加入队列，则不再添加5这个元素
                System.out.println(queue.offer("5", 3, TimeUnit.SECONDS));
                System.out.println("after add '5',queue's :" + queue.toString());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        thread.start();
        System.out.println(queue.poll());
        System.out.println("queue's :" + queue.toString());
    }

    private static void testConcurrentQueue() {
        ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();
        queue.add("1");
        queue.add("2");
        queue.add("3");
        System.out.printf("queue's top: %s %n", queue.peek());
        System.out.printf("queue's size: %s %n", queue.size());
        System.out.printf("queue's: %s %n", queue.toString());

        System.out.printf("queue's top: %s %n", queue.poll());
        System.out.printf("queue's size: %s %n", queue.size());
        System.out.printf("queue's: %s %n", queue.toString());


    }
}
